#pragma once

#include <stdint.h>
#include <cmath>
#include <bit>

template <typename T>
class BigEndian
{
public:
    T value;

public:
    constexpr T val() const
    {
        if constexpr (sizeof(T) == 1)
            return value;
        else if constexpr (sizeof(T) == 2)
            return __builtin_bswap16(value);
        else if constexpr (sizeof(T) == 4)
            return __builtin_bswap32(value);
        else if constexpr (sizeof(T) == 8)
            return __builtin_bswap64(value);
        else
            static_assert(sizeof(T) != sizeof(T), "Unsupported size for T");
    }
};

inline static constexpr double ConvertNumberToFloat(uint64_t number, bool isDoublePrecision)
{
    int mantissaShift = isDoublePrecision ? 52 : 23;
    unsigned long exponentMask = isDoublePrecision ? 0x7FF0000000000000 : 0x7f800000;
    int bias = isDoublePrecision ? 1023 : 127;
    int signShift = isDoublePrecision ? 63 : 31;

    int sign = (number >> signShift) & 0x01;
    int exponent = ((number & exponentMask) >> mantissaShift) - bias;

    int power = -1;
    double total = 0.0;
    for (int i = 0; i < mantissaShift; i++)
    {
        int calc = (number >> (mantissaShift - i - 1)) & 0x01;
        total += calc * pow(2.0, power);
        power--;
    }
    double value = (sign ? -1 : 1) * pow(2.0, exponent) * (total + 1.0);

    return value;
}

struct VInt
{
private:
    int64_t deczz(uint64_t n)
    {
        return (n >> 1) ^ (-(n & 1));
    }

public:
    int64_t val()
    {
        uint64_t value = 0;
        uint8_t *p = (uint8_t *)this;
        while (*p & 0x80)
        {
            ++p;
        }
        while (p >= (uint8_t *)this)
        {
            value = (value << 7) | (*p & 0x7f);
            --p;
        }
        return value;
    }
    /**
     * @brief 返回VInt的byte数
     */
    size_t size()
    {
        uint8_t *p = (uint8_t *)this;
        while (*p & 0x80)
            ++p;
        return p - (uint8_t *)this + 1;
    }
};

struct Double
{
    uint64_t value;
    double val()
    {
        return ConvertNumberToFloat(value, true);
    }
};

#pragma pack(1)

// 每个域都有域头和域体组成
struct FiledHeader
{
    int16_t filed_id;
    int16_t filed_length; // 域体长度
};

#pragma pack()
